package ms.unicorn.dsl.eistar.reasoning.maxbelief;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ms.unicorn.dsl.eistar.reasoning.ReasoningException;
import ms.unicorn.dsl.eistar.util.Probability;
import ms.unicorn.utils.Console;

import eistar.Entity;
import eistar.EvolutionBranch;
import eistar.EvolutionModel;
import eistar.EvolutionRule;
import eistar.Model;

public class MaxBeliefReasoning {
	
	private Map<Entity, MaxBeliefTable> mbTables;
	
	public MaxBeliefReasoning() {
		mbTables = new HashMap<Entity, MaxBeliefTable>();
	}
	
	public MaxBeliefTable performReasoning(EvolutionModel model) {
		List<EvolutionRule> rules = model.getRules();
		ArrayList<MaxBeliefTable> tables = new ArrayList<MaxBeliefTable>(rules.size());
		
		for(EvolutionRule rule: rules) {
			tables.add(performReasoning(rule));
		}
		
		Model orgModel = model.getModel();
		MaxBeliefTable table = new MaxBeliefTable();
		table.generateFromModel(orgModel, tables);
		return table;
	}
	
	public MaxBeliefTable performReasoning(EvolutionRule rule) {
		/*MaxBeliefTable result = openMbTable(rule);
		result.generateFromModel(rule.getOriginal());*/
		
		Console.println(">>Estimating max belief table of rule %s", rule.getName());
		
		int defaultMb = Probability.ONE;
		
		MaxBeliefTable globalTable = null;
		
		for(EvolutionBranch branch: rule.getAllBranches()) {
			MaxBeliefTable btable = openMbTable(branch);
			btable.generateFromModel(branch);
			btable.resetMaxBelief(branch.getProbability());
			btable.resetResidualRisk(Probability.complement(branch.getProbability()));
			// debug-begin
			Console.println("...table of branch: %s", branch.getName());
			btable.printTableContent();
			Console.println();
			// debug-end
			defaultMb -= branch.getProbability();
			
			globalTable = globalTable != null ? globalTable.merge(btable) : btable;
			
			// debug-begin
			Console.println("** updated global table:");
			globalTable.printTableContent();
			Console.println();
			// debug-end
		}
		
		if (defaultMb > 0) 
			throw new ReasoningException("Total probabilities is less than 1");
		
		
		/*result.setMaxBelief(defaultMb);
		result.setResidualRisk(Probability.complement(defaultMb));
		
		result.merge(btables);*/
		
		setMbTable(rule, globalTable);
			
		return globalTable;
	}
	
	public MaxBeliefTable getMbTable(Entity model) {
		return mbTables.get(model);
	}
	
	public void setMbTable(Entity entity, MaxBeliefTable table) {
		mbTables.put(entity, table);
	}
	
	public MaxBeliefTable openMbTable(Entity entity) {
		MaxBeliefTable res = mbTables.get(entity);
		if (res == null)
			mbTables.put(entity, res = new MaxBeliefTable());
		return res;
	}
}
